import React from 'react'
import { Button, Upload, message as antdMessage } from 'antd'
import './style.css'
import uploadUrl from '../../assets/image/upload.webp'
import { UploadRequestOption } from 'rc-upload/lib/interface'
import SparkMD5 from 'spark-md5'
import axios from 'axios'

interface ChunkType {
	name: string
	chunk: Blob
}

const Index: React.FC = () => {
	const customRequest = async (options: UploadRequestOption) => {
		// 获取上传的文件
		const file = options.file as File
		// 文件扩展名
		const extname = file.name.slice(file.name.lastIndexOf('.'))
		// 获取上传文件的hash
		const hash = await createFileMD5Hash(file)
		// 请求后端文件检查接口
		const checkFileResult = await checkFile(hash)
		// 获取检测信息
		const { code, message, data } = checkFileResult.data;


		// 根据状态码 判断
		if (code === 200 || code === 202) {
			// 没有上传 || 上传了一部分

			// 准备上传的分片
			let chunks = createFileChunks(file, hash, extname)
			// 已经上传的分片
			const existsChunks = data.existsChunks || []

			// 断点续传
			chunks = chunks.filter(v => {
				return !existsChunks.includes(v.name)
			})
			
			// 将分片转化 FormData
			const formDataChunk = chunks.map(v => {
				const form = new FormData();
				form.append('file', v.chunk, v.name)
				return form
			})
			// 发送所有请求
			const requestAll = formDataChunk.map(formData => {
				return axios.post('/api/upload', formData)
			})

			// 有等待所有请求成功
			const result = await Promise.all(requestAll)
			// 合并切片
			await axios.post('/api/merge/file', { hash, extname })

			antdMessage.success('上传Ok')
		} else {
			// 已经上传完毕 或者 上传了一部分
			if (code === 201) {
				antdMessage.success('秒传成功')
			}
		}
	}

	// 创建md5 hash file
	const createFileMD5Hash = (file: File): Promise<string> => {
		return new Promise((resolve, reject) => {
			let blobSlice = File.prototype.slice,
				chunkSize = 2097152,                             // Read in chunks of 2MB
				chunks = Math.ceil(file.size / chunkSize),
				currentChunk = 0,
				spark = new SparkMD5.ArrayBuffer(),
				fileReader = new FileReader();

			fileReader.onload = function (e) {
				if (e.target && e.target.result !== null && typeof e.target.result !== 'string')
					spark.append(e.target.result);                   // Append array buffer
				currentChunk++;

				if (currentChunk < chunks) {
					loadNext();
				} else {
					resolve(spark.end())
				}
			};

			fileReader.onerror = function () {
				console.warn('oops, something went wrong.');
			};

			function loadNext() {
				var start = currentChunk * chunkSize,
					end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;

				fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
			}

			loadNext();
		})
	}
	// 检车文件函数
	const checkFile = (hash: string) => {
		return axios.post('/api/check/file', { hash })
	}
	// 文件分片
	const createFileChunks = (file: File, hash: string, extname: string, chunkSize = 2 * 1024 ** 2) => {
		const maxIndex = Math.ceil(file.size / chunkSize);
		const chunks: ChunkType[] = []
		for (let i = 0; i < maxIndex; i++) {
			const start = i * chunkSize
			const end = start + chunkSize > file.size ? file.size : start + chunkSize
			chunks.push({
				name: `${hash}-${i}${extname}`,
				chunk: file.slice(start, end)
			})
		}
		return chunks
	}

	return (
		<div>
			<div className='upload'>
				<Upload customRequest={(options) => customRequest(options)}>
					<Button type="primary">上传文件</Button>
				</Upload>
			</div>
		</div>
	)
}


export default Index